package com.osmino.contacts.list;

import java.util.ArrayList;
import java.util.List;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentUris;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.SparseBooleanArray;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.osmino.contacts.IntentsTable;
import com.osmino.contacts.R;
import com.osmino.contacts.entity.Contact;
import com.osmino.contacts.entity.Email;
import com.osmino.contacts.entity.Phone;
import com.osmino.contacts.help.HelpActivity;
import com.osmino.contacts.provider.ContactsContractQueries;
import com.osmino.contacts.provider.ContactsContractResolver;
import com.osmino.contacts.provider.ContactsContractResolver.ContactsDataObserver;
import com.osmino.contacts.search.SearchDublicatesActivity;
import com.osmino.contacts.settings.SettingsActivity;
import com.osmino.contacts.sideindex.AlphabetIndexView;
import com.osmino.contacts.sideindex.AlphabetIndexView.AlphabetIndexListener;
import com.osmino.contacts.sideindex.SectionController;
import com.osmino.core.AbsListActivity;
import com.osmino.core.DialogGenerator;
import com.osmino.core.DialogInfo;
import com.osmino.core.IContactListBottomPanelController;
import com.osmino.core.TextPickerDialog;

public final class ContactsListActivity extends AbsListActivity implements IContactsController, ContactsDataObserver,
		TextWatcher, AlphabetIndexListener, SectionController, IContactListBottomPanelController {

	private ContactsContractResolver mContactsContractResolver;
	private ContactsSectionAdapter mAdapter;
	private TextView mTitleBarText;
	private DialogGenerator mDialogGenerator;
	private ImageView mEditIcon, mAddIcon;
	private EditText mSearchText;
	private int mListRegime;
	private int mCandidateForDelete = -1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mContactsContractResolver = mHostApplication.getContactsContractResolver();
		if (getParent() == null) {
			if (!mContactsContractResolver.isCreated()) {
				mContactsContractResolver.create();
			}
		}
		mDialogGenerator = new DialogGenerator(this, this);
		setContentView(R.layout.contacts_view);
		mActionContactType = getIntent().getAction();
		mTitleBarText = (TextView) findViewById(R.id.title_bar_text);
		mEditIcon = (ImageView) findViewById(R.id.title_bar_edit_icon);
		mAddIcon = (ImageView) findViewById(R.id.title_bar_add_icon);
		prepTitle();
		mSearchText = (EditText) findViewById(R.id.contacts_search_text);
		mAdapter = new ContactsSectionAdapter(this, ContactsBaseAdapter.FROM_CONTACTS, this);
		getListView().setTextFilterEnabled(true);
		getListView().setVerticalScrollBarEnabled(false);
		setListAdapter(mAdapter);
		getListView().setOnItemClickListener(this);
		registerForContextMenu(getListView());
		String action = getIntent().getAction();
		if (IntentsTable.ACTION_CONTACTS_LIST.equals(action)) {
			setListRegime(LIST_REGIME_OVERVIEW);
		} else {
			setListRegime(LIST_REGIME_EDIT);
		}
		mEditIcon.setOnClickListener(this);
		mAddIcon.setOnClickListener(this);
		mSearchText.addTextChangedListener(this);
		mContactsContractResolver.registerContactsDataObserver(this);
		if (!mContactsContractResolver.isContactListsReady()) {
			showDialog(R.id.dialog_waiting);
		} else {
			initContactList();
		}
		buildButtonPanel();
		initSideIndex();
	}

	private void prepTitle() {
		mEditIcon.setVisibility(View.GONE);
	}

	private void initContactList() {
		List<Contact> listContacts = mContactsContractResolver.getListContacts();
		buildStringForTitleBar(listContacts.size());
		mAdapter.setListContacts(listContacts);
		getListView().clearChoices();
		setSideIndexArray(listContacts);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		mContactsContractResolver.unregisterContactsDataObserver(this);
		if (getParent() == null) {
			mContactsContractResolver.destroy();
		}
		mAdapter = null;
		mTitleBarText = null;
		mEditIcon = null;
		mAddIcon = null;
		mSearchText = null;
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		Dialog dialog = null;
		switch (id) {
			case R.id.dialog_edit_before_call:
				dialog = mDialogGenerator.createEditBeforeCallDialog();
				break;
			case R.id.dialog_quick_message:
				dialog = mDialogGenerator.createQuickMessageDialog(null, null);
				break;
			case R.id.dialog_delete_contact:
				dialog = mDialogGenerator.createDeleteContactDialog();
				break;
			case R.id.dialog_waiting:
				dialog = mDialogGenerator.createWaitingDialog();
				break;
			default:
				dialog = super.onCreateDialog(id);
		}
		return dialog;
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		switch (id) {
			case R.id.dialog_edit_before_call:
				mDialogGenerator.prepareEditBeforeCallDialog((TextPickerDialog) dialog);
				break;
			case R.id.dialog_quick_message:
				mDialogGenerator.prepareQuickMessageDialog((AlertDialog) dialog);
				break;
		}
	}

	@Override
	public void onDialogCallback(DialogInfo dialogCallbackInfo) {
		int dialogId = dialogCallbackInfo.dialogId;
		if (dialogId == R.id.dialog_edit_before_call) {
			onEditBeforeCallDialogCallback(dialogCallbackInfo);
		} else if (dialogId == R.id.dialog_delete_contact) {
			onDeleteDialogCallback(dialogCallbackInfo);
		}
	}

	private void onEditBeforeCallDialogCallback(DialogInfo dialogCallbackInfo) {
		int whichButton = dialogCallbackInfo.whichButton;
		String text = dialogCallbackInfo.text;
		if (whichButton == Dialog.BUTTON_POSITIVE) {
			Uri callUri = Uri.parse("tel:" + text);
			Intent callIntent = new Intent(Intent.ACTION_CALL, callUri);
			startActivity(callIntent);
		}
	}

	private void onDeleteDialogCallback(DialogInfo dialogCallbackInfo) {
		Contact contact = (Contact) mAdapter.getItem(mCandidateForDelete);
		ContactsContractQueries.deleteContact(this, contact.id);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.contacts_option_menu, menu);
		return IntentsTable.ACTION_CONTACTS_LIST.equals(mActionContactType);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int itemId = item.getItemId();
		switch (itemId) {
			case R.id.contact_option_create:
				onOptionCreateContact();
				break;
			case R.id.contact_option_search_by_name:
				onOptionSearch(IntentsTable.EXTRA_MERGE_BY_NAME);
				break;
			case R.id.contact_option_search_by_phone:
				onOptionSearch(IntentsTable.EXTRA_MERGE_BY_PHONE);
				break;
			case R.id.contact_option_search_by_email:
				onOptionSearch(IntentsTable.EXTRA_MERGE_BY_EMAIL);
				break;
			case R.id.contact_option_merge:
				onOptionMerge();
				break;
			case R.id.contact_option_delete:
				onOptionDelete();
				break;
			case R.id.contact_option_import_from_SIM:
				onOptionImportFromSim();
				break;
			case R.id.contact_option_import_from_SD:
				onOptionImportFromSD();
				break;
			case R.id.contact_option_export_to_SD:
				onOptionExportFromSD();
				break;
			case R.id.contact_option_manage_accounts:
				onOptionManageAccounts();
				break;
			case R.id.contact_option_send_vcard:
				onOptionSendVCard();
				break;
			case R.id.contact_option_settings:
				onOptionSettings();
				break;
			case R.id.contact_option_help:
				onOptionHelp();
				break;
		}
		return super.onOptionsItemSelected(item);
	}

	private void onOptionCreateContact() {
		Intent activityCall = new Intent(Intent.ACTION_INSERT);
		activityCall.setData(ContactsContract.Contacts.CONTENT_URI);
		startActivity(activityCall);
	}
	
	private void onOptionSearch(int searchMode) {
		Intent activityCall = new Intent(this, SearchDublicatesActivity.class);
		activityCall.putExtra(IntentsTable.EXTRA_MERGE_AUTOMATIC, searchMode);
		startActivity(activityCall);
	}

	private void onOptionMerge() {
		Intent activityCall = new Intent(IntentsTable.ACTION_CONTACTS_MERGE);
		activityCall.setData(ContactsContract.Contacts.CONTENT_URI);
		activityCall.setPackage(getPackageName());
		startActivity(activityCall);
	}

	private void onOptionDelete() {
		Intent activityCall = new Intent(Intent.ACTION_DELETE);
		activityCall.addCategory(Intent.CATEGORY_DEFAULT);
		activityCall.setData(ContactsContract.Contacts.CONTENT_URI);
		activityCall.setPackage(getPackageName());
		startActivity(activityCall);
	}

	private void onOptionImportFromSim() {
		
	}

	private void onOptionImportFromSD() {
	}

	private void onOptionExportFromSD() {
	}

	private void onOptionManageAccounts() {
	}

	private void onOptionSendVCard() {
	}

	private void onOptionSettings() {
		Intent activityCall = new Intent(this, SettingsActivity.class);
		startActivity(activityCall);
	}

	private void onOptionHelp() {
		Intent activityCall = new Intent(this, HelpActivity.class);
		startActivity(activityCall);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, view, menuInfo);
		mActionContactType = getIntent().getAction();
		if (!IntentsTable.ACTION_CONTACTS_LIST.equals(mActionContactType)) {
			return;
		}
		int viewId = view.getId();
		if (viewId == getListView().getId()) {
			if (mListRegime == LIST_REGIME_OVERVIEW) {
				getMenuInflater().inflate(R.menu.contacts_context_menu, menu);
				Contact contact = (Contact) mAdapter.getItem(((AdapterView.AdapterContextMenuInfo) menuInfo).position);
				if (contact.getPhones().size() == 0) {
					menu.removeItem(R.id.contact_option_call);
					menu.removeItem(R.id.contact_option_edit_before_call);
					menu.removeItem(R.id.contact_option_send_SMS);
				}
				if (contact.getEmails().size() == 0) {
					menu.removeItem(R.id.contact_option_send_email);
				}
			}
		}
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo();
		int itemId = item.getItemId();
		switch (itemId) {
			case R.id.contact_option_call:
				onContextOptionCall((AdapterContextMenuInfo) menuInfo);
				break;
			case R.id.contact_option_edit_before_call:
				onContextOptionEditBeforeCall((AdapterContextMenuInfo) menuInfo);
				break;
			case R.id.contact_option_send_SMS:
				onContextOptionSendSms((AdapterContextMenuInfo) menuInfo);
				break;
			case R.id.contact_option_send_contact_by_SMS:
				onContextOptionSendContactBySms((AdapterContextMenuInfo) menuInfo);
				break;
			case R.id.contact_option_send_email:
				onContextOptionSendEmail((AdapterContextMenuInfo) menuInfo);
				break;
			case R.id.contact_option_edit_contact:
				onContextOptionEditContact((AdapterContextMenuInfo) menuInfo);
				break;
			case R.id.contact_option_delete_contact:
				onContextOptionDeleteContact((AdapterContextMenuInfo) menuInfo);
				break;
		}
		return false;
	}

	@Override
	public void onClick(View view) {
		int viewId = view.getId();
		if (viewId == R.id.title_bar_edit_icon) {
			if (mListRegime == LIST_REGIME_OVERVIEW) {
				onEditClick();
			} else if (mListRegime == LIST_REGIME_EDIT) {
				onOverviewClick();
			}
		} else if (viewId == R.id.title_bar_add_icon) {
			onAddClick();
		}
		// <Bottom panel staff>
		int actionType = 0;
		if (IntentsTable.ACTION_CONTACTS_LIST.equals(mActionContactType)) {
			actionType = 0;
		} else if (Intent.ACTION_DELETE.equals(mActionContactType)) {
			actionType = 1;
		} else if (IntentsTable.ACTION_CONTACTS_MERGE.equals(mActionContactType)) {
			actionType = 2;
		}
		switch (viewId) {
			case R.id.contact_check_buttons_1:
				if (actionType == 1) {
					onDeleteClick();
				} else if (actionType == 2) {
					onMergeClick();
				}
				break;
			case R.id.contact_check_buttons_2:
				if (actionType == 1) {
					onSelectAllClick();
				} else if (actionType == 2) {
					onCancelClick();
				}
				break;
			case R.id.contact_check_buttons_3:
				if (actionType == 1) {
					onCancelClick();
				}
				break;
		}
		// </Bottom panel staff>
	}

	@Override
	public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
		int viewId = adapterView.getId();
		if (viewId == android.R.id.list) {
			if (mListRegime == LIST_REGIME_OVERVIEW) {
				Contact contact = getContactForPosition(position);
				Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contact.id);
				Intent activityCall = new Intent(Intent.ACTION_VIEW, contactUri);
				activityCall.setPackage(getPackageName());
				startActivity(activityCall);
			}
		}
	}

	@Override
	public void onAddClick() {
		Intent insertIntent = new Intent(Intent.ACTION_INSERT);
		insertIntent.setData(ContactsContract.Contacts.CONTENT_URI);
		startActivity(insertIntent);
	}

	@Override
	public void onOverviewClick() {
		setListRegime(LIST_REGIME_OVERVIEW);
	}

	@Override
	public void onEditClick() {
		setListRegime(LIST_REGIME_EDIT);
	}

	private Contact getContactForPosition(int position) {
		Contact contact = (Contact) mAdapter.getItem(position);
		return contact;
	}

	private void onContextOptionCall(AdapterView.AdapterContextMenuInfo menuInfo) {
		Contact contact = getContactForPosition(menuInfo.position);
		Phone phone = contact.getPhones().get(0);
		Uri callUri = Uri.parse("tel:" + phone.number);
		Intent callIntent = new Intent(Intent.ACTION_CALL, callUri);
		startActivity(callIntent);
	}

	private void onContextOptionEditBeforeCall(AdapterView.AdapterContextMenuInfo menuInfo) {
		Contact contact = getContactForPosition(menuInfo.position);
		Phone phone = contact.getPhones().get(0);
		mDialogGenerator.setDialogText(R.id.dialog_edit_before_call, phone.number);
		showDialog(R.id.dialog_edit_before_call);
	}

	private void onContextOptionSendSms(AdapterView.AdapterContextMenuInfo menuInfo) {
	}

	private void onContextOptionSendContactBySms(AdapterView.AdapterContextMenuInfo menuInfo) {
	}

	private void onContextOptionSendEmail(AdapterView.AdapterContextMenuInfo menuInfo) {
		Contact contact = getContactForPosition(menuInfo.position);
		Email email = contact.getEmails().get(0);
	}

	private void onContextOptionEditContact(AdapterView.AdapterContextMenuInfo menuInfo) {
		Contact contact = getContactForPosition(menuInfo.position);
		Uri editUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contact.id);
		Intent intent = new Intent(Intent.ACTION_EDIT, editUri);
		startActivity(intent);
	}

	private void onContextOptionDeleteContact(AdapterView.AdapterContextMenuInfo menuInfo) {
		mCandidateForDelete = menuInfo.position;
		showDialog(R.id.dialog_delete_contact);
	}

	@Override
	public int getListRegime() {
		return mListRegime;
	}

	public void setListRegime(int regime) {
		System.out.println("regime:" + regime);
		mListRegime = regime;
		if (mListRegime == LIST_REGIME_OVERVIEW) {
			getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
			mAdapter.setShowCheckboxes(false);
		} else {
			getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
			getListView().clearChoices();
			mAdapter.setShowCheckboxes(true);
		}
		mAdapter.notifyDataSetChanged();
	}

	private void buildStringForTitleBar(int count) {
		StringBuilder sb = new StringBuilder();
		if (mListRegime == LIST_REGIME_OVERVIEW) {
			sb.append(getString(R.string.all_contacts));
			sb.append(" (").append(count).append(")");
		} else {
			if (IntentsTable.ACTION_CONTACTS_MERGE.equals(mActionContactType)) {
				sb.append(getString(R.string.choose_contacts_to_merge));
			} else if (Intent.ACTION_DELETE.equals(mActionContactType)) {
				sb.append(getString(R.string.choose_contacts_to_delete));
			}
		}
		mTitleBarText.setText(sb.toString());
	}

	@Override
	public void afterTextChanged(Editable s) {
		String text = s.toString();
		mAdapter.getFilter().filter(text);
	}

	@Override
	public void beforeTextChanged(CharSequence s, int start, int count, int after) {//
	}

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {//
	}

	@Override
	public void onStartRefresh() {
		showDialog(R.id.dialog_waiting);
	}

	@Override
	public void onRefreshContactsSctructure() {
		dismissDialog(R.id.dialog_waiting);
		initContactList();
	}

	@Override
	public void onAdapterContactsChanged(List<Contact> listContacts) {
		buildStringForTitleBar(listContacts.size());
		setSideIndexArray(listContacts);
	}

	// Alphabet staff
	private void initSideIndex() {
		AlphabetIndexView view = (AlphabetIndexView) findViewById(R.id.sideIndex);
		view.setAlphabetIndexListener(this);
	}

	private void setSideIndexArray(List<Contact> listContacts) {
		int len = listContacts.size();
		AlphabetIndexView view = (AlphabetIndexView) findViewById(R.id.sideIndex);
		if (len > 0) {
			String[] listForIndex = new String[len];
			String tmpName;
			for (int i = 0; i < len; i++) {
				tmpName = listContacts.get(i).displayName;
				if (!TextUtils.isEmpty(tmpName))
					listForIndex[i] = tmpName;
				else
					listForIndex[i] = " ";
			}
			view.refreshIndex(listForIndex);
		} else {
			view.setVisibility(View.INVISIBLE);
		}
	}

	@Override
	public void onComputeListItem(int item) {
		int sectPoses = 0;
		int realPos = 0;
		while (realPos < (item + sectPoses)) {
			realPos++;
			sectPoses = mAdapter.getSectionForPosition(realPos);
		}
		int position = item + sectPoses;
		if (position < getListView().getCount()) {
			getListView().setSelection(position);
			Object o = getListView().getAdapter().getItem(position);
			if (o instanceof Contact) {
				showLetter(((Contact) o).displayName.substring(0, 1));
			}
		}
	}

	@Override
	public void onScroll() {
	}

	private void showLetter(String text) {
		boolean isShown;
		int delay = 1000;
		final TextView letter = (TextView) findViewById(R.id.abc_big_letter);
		isShown = letter.getVisibility() == View.VISIBLE;
		if (!isShown) {
			letter.setVisibility(View.VISIBLE);
			letter.postDelayed(new Runnable() {

				@Override
				public void run() {
					letter.setVisibility(View.INVISIBLE);
					letter.setText("");
				}
			}, delay);
		} else {
			if (!TextUtils.isEmpty(text))
				letter.setText(text.toUpperCase());
			return;
		}
	}

	// EOF Alphabet staff
	// Bottom Button Panel Staff
	private final static int B_PAN_GONE = 0;
	private final static int B_PAN_VISIBLE = 1;
	private final static int B_PAN_BUTT1_VISIBLE = 1 << 1;
	private final static int B_PAN_BUTT2_VISIBLE = 1 << 2;
	private final static int B_PAN_BUTT3_VISIBLE = 1 << 3;
	private int mButtonPanelFlag = 0;
	private String mActionContactType;

	private boolean isButtonPanelFlag(int flag) {
		return flag == (mButtonPanelFlag & flag);
	}

	private void buildButtonPanel() {
		if (IntentsTable.ACTION_CONTACTS_LIST.equals(mActionContactType)) {
			mButtonPanelFlag = B_PAN_GONE;
		} else if (Intent.ACTION_DELETE.equals(mActionContactType)) {
			mButtonPanelFlag = (B_PAN_VISIBLE | B_PAN_BUTT1_VISIBLE | B_PAN_BUTT2_VISIBLE | B_PAN_BUTT3_VISIBLE);
			((Button) findViewById(R.id.contact_check_buttons_1)).setText(R.string.delete);
			((Button) findViewById(R.id.contact_check_buttons_2)).setText(R.string.select_all);
			((Button) findViewById(R.id.contact_check_buttons_3)).setText(R.string.cancel);
			findViewById(R.id.contact_check_buttons_1).setOnClickListener(this);
			findViewById(R.id.contact_check_buttons_2).setOnClickListener(this);
			findViewById(R.id.contact_check_buttons_3).setOnClickListener(this);
		} else if (IntentsTable.ACTION_CONTACTS_MERGE.equals(mActionContactType)) {
			mButtonPanelFlag = (B_PAN_VISIBLE | B_PAN_BUTT1_VISIBLE | B_PAN_BUTT2_VISIBLE);
			((Button) findViewById(R.id.contact_check_buttons_1)).setText(R.string.merge);
			((Button) findViewById(R.id.contact_check_buttons_2)).setText(R.string.cancel);
			findViewById(R.id.contact_check_buttons_1).setOnClickListener(this);
			findViewById(R.id.contact_check_buttons_2).setOnClickListener(this);
		}
		findViewById(R.id.contact_check_buttons_root).setVisibility(
				isButtonPanelFlag(B_PAN_VISIBLE) ? View.VISIBLE : View.GONE);
		findViewById(R.id.contact_check_buttons_1).setVisibility(
				isButtonPanelFlag(B_PAN_BUTT1_VISIBLE) ? View.VISIBLE : View.GONE);
		findViewById(R.id.contact_check_buttons_2).setVisibility(
				isButtonPanelFlag(B_PAN_BUTT2_VISIBLE) ? View.VISIBLE : View.GONE);
		findViewById(R.id.contact_check_buttons_3).setVisibility(
				isButtonPanelFlag(B_PAN_BUTT3_VISIBLE) ? View.VISIBLE : View.GONE);
	}

	@Override
	public void onDeleteClick() {
		List<Contact> deleteList = new ArrayList<Contact>();
		SparseBooleanArray checkedItems = getListView().getCheckedItemPositions();
		int count = getListView().getCount();
		for (int i = 0; i < count; i++) {
			if (checkedItems.get(i)) {
				Object item = mAdapter.getItem(i);
				if (item instanceof Contact) {
					deleteList.add((Contact) item);
				}
			}
		}
		ContactsContractQueries.deleteContacts(this, deleteList);
	}

	@Override
	public void onSelectAllClick() {
		int count = getListView().getCount();
		for (int i = 0; i < count; i++) {
			getListView().setItemChecked(i, true);
		}
	}

	@Override
	public void onCancelClick() {
		finish();
	}

	@Override
	public void onMergeClick() {
		List<Contact> mergeList = new ArrayList<Contact>();
		SparseBooleanArray checkedItems = getListView().getCheckedItemPositions();
		int count = getListView().getCount();
		for (int i = 0; i < count; i++) {
			if (checkedItems.get(i)) {
				Object item = mAdapter.getItem(i);
				if (item instanceof Contact) {
					mergeList.add((Contact) item);
				}
			}
		}
		if (mergeList.size() > 1) {
			Contact mainContact = mergeList.get(0);
			mergeList.remove(mainContact);
			ContactsContractQueries.mergeContacts(this, mainContact, mergeList);
		}
	}
	// EOF Bottom Button Panel Staff
}
